package remotecall.call;

import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.zjw.zy.utils.LogUtils;

import java.util.Objects;
import java.util.concurrent.atomic.AtomicLong;

import remotecall.streamacceptor.RemoteCallResult;
import remotecall.utils.RemoteUtils;

/**
 * @author zhongjiwei
 * 可复用的远程回调
 */
public class IRemoteCall<T> implements Parcelable {

    private static final String TAG = "IRemoteCall";

    private final IRemoteWithIt remoteCall;

    private static final AtomicLong sRequestIndex = new AtomicLong(0);

    private final String mRequestId;

    private final String mDescriptor;

    public IRemoteCall(String descriptor) {
        mDescriptor = descriptor;
        remoteCall = new RemoteWithIt<T>(mDescriptor) {
            @Override
            public void onWith(T t) {
                IRemoteCall.this.onWith(t);
            }
        };
        mRequestId = sRequestIndex.getAndIncrement() + TAG + "r@" + RemoteUtils.forLong();
    }

    public IRemoteCall() {
        this(RemoteUtils.createDefaultDescriptor() + "@call");
    }


    protected IRemoteCall(Parcel in) {
        mDescriptor = in.readString();
        remoteCall = IRemoteWithIt.Stub.asInterface(in.readStrongBinder(), mDescriptor);
        mRequestId = in.readString();
    }

    public static final Creator<IRemoteCall<?>> CREATOR = new Creator<IRemoteCall<?>>() {
        @Override
        public IRemoteCall<?> createFromParcel(Parcel in) {
            return new IRemoteCall<>(in);
        }

        @Override
        public IRemoteCall<?>[] newArray(int size) {
            return new IRemoteCall[size];
        }
    };

    /**
     * 需要重写的方法
     */
    public void onWith(T obj) {

    }

    @Override
    public int describeContents() {
        return 0;
    }

    /**
     * 跨进程回调结果
     */
    public void call(@Nullable T t) {
        try {
            remoteCall.onWith(new RemoteCallResult(t));
        } catch (RemoteException e) {
            LogUtils.e(TAG, "call: " + e.getMessage());
        }
    }

    /**
     * 跨进程回调结果
     */
    public void call(Object... args) {
        try {
            remoteCall.onWith(new RemoteCallResult(args));
        } catch (RemoteException e) {
            LogUtils.e(TAG, "call: " + e.getMessage());
        }
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(mDescriptor);
        dest.writeStrongBinder(remoteCall != null ? remoteCall.asBinder() : null);
        dest.writeString(mRequestId);
    }

    @NonNull
    @Override
    public String toString() {
        return "IRemoteCall{" +
                "mRequestId='" + mRequestId + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        IRemoteCall<?> that = (IRemoteCall<?>) o;
        return mRequestId.equals(that.mRequestId);
    }

    @Override
    public int hashCode() {
        return Objects.hash(mRequestId);
    }
}
